package net.wicp.tams.common.micro;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.stereotype.Service;

@Service
public class SpringBootAssit {
	@Autowired
	private Environment environment;

	private String[] lastConfNeedStart = new String[] { "configService:" };

	public Map<String, String> findAllProps() {
		Map<String, LinkedHashMap<String, String>> retlist = findAllPropsCollect();
		LinkedHashMap<String, String> allMap = new LinkedHashMap<>();
		List<LinkedHashMap<String, String>> lastPut = new ArrayList<>();
		for (String ele : retlist.keySet()) {
			boolean isLast = false;
			for (String lastconf : lastConfNeedStart) {
				if (ele.startsWith(lastconf)) {
					isLast = true;
					break;
				}
			}
			if (isLast) {
				lastPut.add(retlist.get(ele));
			} else {
				LinkedHashMap<String, String> tempmap = retlist.get(ele);
				allMap.putAll(tempmap);
			}
		}
		for (LinkedHashMap<String, String> linkedHashMap : lastPut) {
			allMap.putAll(linkedHashMap);
		}
		return allMap;
	}

	public Map<String, LinkedHashMap<String, String>> findAllPropsCollect() {
		Map<String, LinkedHashMap<String, String>> result = new LinkedHashMap<>();
		for (Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
			PropertySource<?> source = entry.getValue();
			String sourceName = entry.getKey();
			if (source instanceof EnumerablePropertySource) {
				EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
				LinkedHashMap<String, String> properties = new LinkedHashMap<String, String>();
				for (String name : enumerable.getPropertyNames()) {
					properties.put(name, String.valueOf(enumerable.getProperty(name)));
				}
				if (properties != null && MapUtils.isNotEmpty(properties)) {
					result.put(sourceName, properties);
				}
			}
		}
		return result;
	}

	private Map<String, PropertySource<?>> getPropertySources() {
		Map<String, PropertySource<?>> map = new LinkedHashMap<String, PropertySource<?>>();
		MutablePropertySources sources = null;
		if (environment != null && environment instanceof ConfigurableEnvironment) {
			sources = ((ConfigurableEnvironment) environment).getPropertySources();
		} else {
			sources = new StandardEnvironment().getPropertySources();
		}
		for (PropertySource<?> source : sources) {
			extract("", map, source);
		}
		return map;
	}

	private void extract(String root, Map<String, PropertySource<?>> map, PropertySource<?> source) {
		if (source instanceof CompositePropertySource) {
			for (PropertySource<?> nest : ((CompositePropertySource) source).getPropertySources()) {
				extract(source.getName() + ":", map, nest);
			}
		} else {
			map.put(root + source.getName(), source);
		}
	}
}
